import { Component, OnInit, ViewEncapsulation, HostListener, ViewChild, ElementRef, Renderer2 } from '@angular/core';
import { FormBuilder, FormGroup, FormControl, Validators } from '@angular/forms';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import { debounceTime } from 'rxjs/operators';

import { MapState, LoadPois, SelectPois, ClearPois, poisSelectors, districtsSelector, AddMarker, ClearMarker } from '../../store';
import { Poi, PlaceTextOption, UserLocation } from '../../../ngx-ol/models';

@Component({
  selector: 'ege-map-search',
  templateUrl: './search.component.html',
  styleUrls: ['./search.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class SearchComponent implements OnInit {

  search: FormGroup;
  pois$: Observable<Poi[]>;
  loaded: boolean;
  loading: boolean;
  showAutocomplate: boolean = false;
  adcode: string;

  @ViewChild('poisList') poisList: ElementRef;

  constructor(
    private store: Store<MapState>,
    private renderer: Renderer2
  ) { }

  ngOnInit() {
    this.store.select(districtsSelector.getDistrictSelected)
      .subscribe((district: UserLocation) => this.adcode = district ? district.adcode : this.adcode);
    this.monitorState();
    this.formBuilder();
    this.setListHeight();
  }

  formBuilder(): void {
    this.search = new FormGroup({
      keywords: new FormControl('', [Validators.required])
    });
    this.search.valueChanges
      .pipe(
        debounceTime(500)
      )
      .subscribe(values => {
        this.searchPois(values.keywords);
      });
  }

  onSubmit(e): void {
    e.preventDefault();
    const values = this.search.value;
    this.searchPois(values.keywords);
  }

  onClickIpt(): void {
    const values = this.search.value;
    this.searchPois(values.keywords);
  }

  searchPois(keywords: string): void {
    if(!keywords) {
      this.hiddenAutocomplate();
      return;
    };
    this.store.dispatch(new LoadPois({keywords: keywords, city: this.adcode }));
  }

  monitorState(): void {
    this.pois$ = this.store.select(poisSelectors.getAllPois);
    this.store.select(poisSelectors.getPoisLoaded).subscribe(loaded => this.loaded = loaded);
    this.store.select(poisSelectors.getPoisLoading).subscribe(loading => {
      this.loading = loading;
      if(!loading) {
        setTimeout(() => {
          this.setListHeight();
        }, 0);
      } else {
        this.loadingAutocomplate();
      }
    });
    this.store.select(poisSelectors.getSelectPois).subscribe((poi: Poi) => {
      const keywords = poi ? poi.address : '';
      // this.setFormControlValue('keywords', keywords);
    });
  }

  setFormControlValue(name: string, value: string|number): void {
    if(!this.search) return;
    let control = this.search.controls[name];
    control.setValue(value, { emitEvent: false });
  }

  @HostListener('document:click', ['$event'])
  onClickOther(e) {
    this.hiddenAutocomplate();
  }

  @HostListener('window:resize', ['$event'])
  onWindowResize(e) {
    if(this.showAutocomplate) {
      this.setListHeight();
    }
  }

  onClickThis(e): void {
    e.stopPropagation();
  }

  setListHeight(): void {
    const windowHeight: number = window.innerHeight;
    const poisListHeight: number = this.poisList.nativeElement.offsetHeight;
    const top: number = this.getElementTop(this.poisList);
    const avilableHeight: number = windowHeight - top - 16;
    const ul = this.poisList.nativeElement.querySelector('#list');
    this.renderer.setStyle(ul, 'opacity', 1);
    const contentHeight = ul.offsetHeight > 0 ? ul.offsetHeight + 1 : ul.offsetHeight;
    const height: number = contentHeight > avilableHeight ? avilableHeight : contentHeight;
    this.renderer.setStyle(this.poisList.nativeElement, 'height', `${height}px`);
    if(this.showAutocomplate) {
      this.renderer.setStyle(this.poisList.nativeElement, 'border-top', '1px solid #eeeeee');
    } else {
      this.renderer.setStyle(this.poisList.nativeElement, 'border-top-width', '0px');
    }
  }

  hiddenAutocomplate(): void {
    this.showAutocomplate = false;
    this.renderer.setStyle(this.poisList.nativeElement, 'height', '0px');
    this.renderer.setStyle(this.poisList.nativeElement, 'min-height', '0px');
    this.renderer.setStyle(this.poisList.nativeElement, 'border-top-width', '0px');
    this.renderer.setStyle(this.poisList.nativeElement.querySelector('#list'), 'opacity', 0);
    this.store.dispatch(new ClearPois());
  }

  loadingAutocomplate(): void {
    this.showAutocomplate = true;    
    this.renderer.setStyle(this.poisList.nativeElement, 'min-height', '40px');
    this.renderer.setStyle(this.poisList.nativeElement, 'border-top', '1px solid #eeeeee');
  }

  getElementTop(element: ElementRef): number {
    let ele = element.nativeElement;
    let height: number = ele.offsetTop;
    while(ele && !(ele instanceof Document)) {
      height+=ele.offsetTop;
      ele = ele.offsetParent;
    }
    return height;
  }

  onClickPoi(poi: Poi): void {
    this.store.dispatch(new SelectPois(poi));
    this.store.dispatch(new ClearMarker());
    this.store.dispatch(new AddMarker({
      title: poi.address,
      point: poi.point
    }));
    this.hiddenAutocomplate();
    this.setFormControlValue('keywords', poi.address);
  }

}
